////////////////////////////////////////
//	File Header
//	Author: Stephen Ringer | stephen.ringer@gmail.com
//	File: SAGARenderDevice.h
//
////////////////////////////////////////
#pragma once
////////////////////////////////////////
//	File Includes
#include <Windows.h>
#include <stdio.h>
#include "../SAGAMath/zfx3d.h"          // zfx 3d math library
#include "../SAGAD3D/SAGA.h"			// MATERIAL structure
//
////////////////////////////////////////

////////////////////////////////////////
//	Macros
#define MAX_3DHWND	8
#define MAX_SHADER  20
typedef enum SAGAZXIS_TYPE {X_AXIS, Y_AXIS, Z_AXIS}SAGAAXIS;
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: SAGASkinManager
//	Purpose:
//		To serve as an abstract class which provides an interface
//		from which material managers can inherit. Those heirs need to 
//		implement a store for texture data in a way appropriate to the
//		API.
class SAGASkinManager 
{
protected:
	UINT         m_nNumSkins;				// number (IDs) of skins
	UINT         m_nNumMaterials;			// number (IDs) of materials
	UINT         m_nNumTextures;			// number (IDs) of materials
	SAGASKIN     *m_pSkins;					// allocate memory for skins
	SAGAMATERIAL *m_pMaterials;				// allocate memory for materials
	SAGATEXTURE  *m_pTextures;				// allocate memory for textures

public:
	SAGASkinManager() {};
	virtual ~SAGASkinManager() {};

	virtual void			Reset(void)=0;
	virtual HRESULT 		AddSkin(const SAGACOLOR *pcAmbient,	const SAGACOLOR *pcDiffuse,
									const SAGACOLOR *pcEmissive,const SAGACOLOR *pcSpecular,
									float fSpecPower, UINT *nSkinID)=0;

	virtual HRESULT 		AddTexture(	UINT nSkinID, const char *chName, bool bAlpha, float fAlpha, 
										SAGACOLOR *cColorKeys, DWORD dwNumColorKeys)=0;

	virtual HRESULT 		AddTextureHeightmapAsBump(UINT nSkinID, const char *chName)=0;
	virtual HRESULT			ExchangeTexture(UINT nSkinID, UINT nTexStage, const char *chName,
											bool bAlpha, float fAlpha, SAGACOLOR *cColorKeys, 
											DWORD dwNumColorKeys)=0;

	virtual HRESULT			ExchangeMaterial(	UINT nSkinID, const SAGACOLOR *pcAmb, 
												const SAGACOLOR *pcDif, const SAGACOLOR *pcEmis, 
												const SAGACOLOR *pcSpec, float fSpecPower)=0;
	virtual bool			ColorEqual(const SAGACOLOR *pCol0, const SAGACOLOR *pCol1)=0;
	virtual bool    		MaterialEqual(const SAGAMATERIAL *pMat0, const SAGAMATERIAL *pMat1)=0;
	virtual UINT			GetNumSkins(void)=0;
	virtual SAGASKIN		GetSkin(UINT nSkinID)=0;
	virtual SAGAMATERIAL	GetMaterial(UINT nMatID)=0;
	virtual const char*		GetTextureName(UINT nTexID, float *pfAlpha, SAGACOLOR *pAK, UCHAR *pNum)=0;
	virtual void    		LogCurrentStatus(char *chLog, bool bDetailed)=0;
};
//
////////////////////////////////////////

////////////////////////////////////////
//	Class Name: SAGAVertexCacheManager
class SAGAVertexCacheManager 
{
public:
	SAGAVertexCacheManager() {};
	virtual ~SAGAVertexCacheManager() {};

	virtual HRESULT CreateStaticBuffer(	SAGAVERTEXID VertexID, UINT  nSkinID, UINT  nVerts, 
										UINT  nIndis, const void *pVerts, const WORD *pIndis, 
										UINT *pnID)=0;

	virtual HRESULT CreateIndexBuffer(UINT nIndis, const WORD *pIndis, UINT *pnID)=0;
	virtual HRESULT Render(	SAGAVERTEXID VertexID, UINT nVerts, UINT nIndis, const void *pVerts, 
							const WORD *pIndis, UINT  SkinID)=0;

	virtual HRESULT RenderNaked(UINT nVerts, const void *pVerts, bool bTextured)=0;
	virtual HRESULT Render(UINT nSBufferID)=0;
	virtual HRESULT Render(UINT SBID, UINT IBID, UINT Skin)=0;
	virtual HRESULT Render(	UINT nSBufferID, UINT SkinID, UINT StartIndex, UINT NumVerts, 
							UINT NumTrims)=0;

	virtual HRESULT RenderPoints(	SAGAVERTEXID VertexID, UINT nVerts, const void *pVerts, 
									const SAGACOLOR *pClrl)=0;

	virtual HRESULT RenderLines(SAGAVERTEXID VertexID, UINT nVerts, const void *pVerts, 
								const SAGACOLOR *pClrl, bool bStrip)=0;

	virtual HRESULT RenderLine(const float *fStart, const float *fEnd, const SAGACOLOR *pClr)=0;
	virtual HRESULT ForcedFlushAll()=0;
	virtual HRESULT ForcedFlush(SAGAVERTEXID)=0;
	virtual void    InvalidateStates()=0;
	virtual SAGARENDERSTATE GetShadeMode()=0;
};
//
////////////////////////////////////////

////////////////////////////////////////
//	Class: SAGARenderDevice
//	Purpose: 
//		To provide an interface with all the functionality of the Rendering Engine
class SAGARenderDevice
{
protected:
	HWND					m_hWndMain;				//	Main Window
	HWND					m_hWnd[MAX_3DHWND];		//	Render Window(s)
	UINT					m_nNumhWnd;				//	Number of Render-Windows
	UINT					m_nActivehWnd;			//	Active Window
	HINSTANCE				m_hDLL;					//	DLL Module
	DWORD					m_dwWidth;				//	Screen Width
	DWORD					m_dwHeight;				//	Screen Height
	bool					m_bWindowed;			//	Windowed Mode?
	char					m_chAdapter[256];		//	Graphics Adapter Name
	bool					m_bRunning;
	bool            		m_bUseShaders;       	// shaders or fixed function pipeline
	bool            		m_bCanDoShaders;     	// hw can do shaders version 1.1
	bool            		m_bAdditive;         	// use additive rendering
	bool            		m_bColorBuffer;      	// use color buffer
	SAGARENDERSTATE			m_ShadeMode;         	// wireframe rendering?
	FILE					*m_pLog;              	// log file
	SAGACOLOR				m_clrWire;           	// color for wireframe rendering

	float					m_fNear,             	// near clipping plane
							m_fFar;              	// far clipping plane
	SAGAENGINEMODE			m_Mode;              	// persp., ortho or 2d
	int						m_nStage;            	// stage (0-3) for viewport/projection
	SAGAVIEWPORT			m_VP[4];             	// viewports for all 4 stages

	SAGASkinManager			*m_pSkinMan;   			// material and textures
	SAGAVertexCacheManager	*m_pVertexMan; 			// manage vertices/indices
public:
	SAGARenderDevice() {};
	virtual ~SAGARenderDevice() {};
	virtual SAGASkinManager* GetSkinManager()=0;
	virtual SAGAVertexCacheManager* GetVertexManager()=0;
	////////////////////////////////////////
	//	Initialization/Shutdown Functions
	virtual HRESULT	Init(HWND, const HWND*, int, int, int, bool)=0;
	virtual HRESULT InitWindowed(HWND, const HWND*, int, bool)=0;
	virtual void	Release()=0;
	virtual bool	IsRunning()=0;
	virtual bool	IsWindowed()=0;
	virtual void	GetResolution(POINT*)=0;
	//
	////////////////////////////////////////

	////////////////////////////////////////
	//	Rendering Functions
	//		Activate or deactivate shaders
	virtual bool    UsesShaders()=0;
	virtual void    UseShaders(bool)=0;
	virtual bool    CanDoShaders()=0;
	virtual HRESULT SetShaderConstant(SAGASHADERTYPE,SAGADATATYPE, UINT,UINT,const void*)=0;
	//		Activate additive blending
	virtual void    UseAdditiveBlending(bool)=0;
	virtual bool    UsesAdditiveBlending()=0;
	//		Set view matrix from cam's vRight, vUp, vDir, vPos
	virtual HRESULT SetView3D(const SAGAVector&, const SAGAVector&, const SAGAVector&, const SAGAVector&)=0;
	//		Set look at matrix: from, at, world up
	virtual HRESULT SetViewLookAt(const SAGAVector&, const SAGAVector&, const SAGAVector&)=0;
	//		Set engines near and far clipping plane
	virtual void    SetClippingPlanes(float, float)=0;
	//		Set mode for stage n, 0:=3D(perspective), 1:=2D(orthogonal)
	virtual HRESULT SetMode(SAGAENGINEMODE, int n)=0;
	virtual void    SetOrthoScale(float fScale, int nStage)=0;
	//		Set perspective FOV and Viewport for stage n
	virtual HRESULT InitStage(float, SAGAVIEWPORT*, int n)=0;
	//		Get frustum planes
	virtual HRESULT GetFrustum(SAGAPlane*)=0;
	//		Screen to worldray, give 2 vectors for output
	virtual void    Transform2Dto3D(const POINT &pt, SAGAVector *vcO, SAGAVector *vcD)=0;
	//		Cast cursor position to ortho world space
	virtual SAGAVector Transform2Dto2D(UINT nHwnd,float,const POINT*,SAGAAXIS)=0;
	//		Cast world position to screen coordinates
	virtual POINT Transform3Dto2D(const SAGAVector &vcP)=0;
	//		Set world transformation matrix or NULL
	virtual void SetWorldTransform(const SAGAMatrix*)=0;
	//		Activate BackFace culling
	virtual void SetBackfaceCulling(SAGARENDERSTATE)=0;
	//		Activate stencil buffer
	virtual void SetStencilBufferMode(SAGARENDERSTATE,DWORD)=0;
	//		Activate stencil shadow volume settings
	virtual void UseStencilShadowSettings(bool)=0;
	//		Activate color buffer
	virtual void UseColorBuffer(bool)=0;
	virtual bool UsesColorBuffer()=0;
	//		Activate usage of texture
	virtual void UseTextures(bool)=0;
	virtual bool UsesTextures()=0;
	//		Activate depth buffer
	virtual void SetDepthBufferMode(SAGARENDERSTATE)=0;
	//      virtual void SetDepthBiasValue(UINT)=0;
	//		Activate wireframe mode
	virtual void SetShadeMode(SAGARENDERSTATE,float,const SAGACOLOR*)=0;
	virtual SAGARENDERSTATE GetShadeMode()=0;
	virtual HRESULT SetTextureStage(UCHAR, SAGARENDERSTATE)=0;
	virtual HRESULT SetLight(const SAGALIGHT*, UCHAR)=0;
	//		Create shaders
	virtual HRESULT CreateVShader(const void *pData, UINT nSize, bool bLoadFromFile, bool bIsCompiled, UINT *pID)=0;
	virtual HRESULT CreatePShader(const void *pData, UINT nSize, bool bLoadFromFile, bool bIsCompiled, UINT *pID)=0;
	virtual HRESULT ActivateVShader(UINT id, SAGAVERTEXID VertexID)=0;
	virtual HRESULT ActivatePShader(UINT id)=0;
	virtual HRESULT	UseWindow(UINT nHwnd)=0;
	virtual HRESULT	BeginRendering(bool bClearPixel, bool bClearDepth, bool bClearStencil)=0;
	virtual void	EndRendering()=0;
	virtual HRESULT Clear(bool bClearPixel, bool bClearDepth, bool bClearStencil)=0;
	virtual void	SetClearColor(float fRed, float fGreen, float fBlue)=0;
	//		Fade screen to given color with given intensity
	virtual void FadeScreen(float fR,float fG,float fB,float fA)=0;
	//		Type like "Arial", nWeight (0=default,700=bold), italic?, 
	//			underline?, strike out?, size, return ID
	virtual HRESULT CreateFont(const char*,int,bool,bool,bool,DWORD,UINT*)=0;
	//		Draw text: font id, x, y, r, g, b, format string, variables
	virtual HRESULT DrawText(UINT,int,int,UCHAR,UCHAR,UCHAR,char*,...)=0;
	//		Set ambient light level
	virtual void SetAmbientLight(float fRed, float fGreen, float fBlue)=0;
	//
	////////////////////////////////////////
};
//
////////////////////////////////////////

////////////////////////////////////////
//	Long Point Declaration to the Class
typedef class SAGARenderDevice *LPSAGARENDERDEVICE;
//
////////////////////////////////////////

////////////////////////////////////////
//	Functions not implemented in 
//		SAGARenderer Static Library
extern "C"
{
	HRESULT CreateRenderDevice(HINSTANCE hDLL, SAGARenderDevice **pInterface);
	typedef HRESULT (*CREATERENDERDEVICE) (HINSTANCE hDL, SAGARenderDevice **pInterface);
	HRESULT ReleaseRenderDevice(SAGARenderDevice **pInterface);
	typedef HRESULT (*RELEASERENDERDEVICE) (SAGARenderDevice **pInterface);
};
//
////////////////////////////////////////